package com.systop.common.modules.security.user.webapp;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.interceptor.validation.SkipValidation;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.type.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;

import com.opensymphony.xwork2.validator.annotations.EmailValidator;
import com.opensymphony.xwork2.validator.annotations.ExpressionValidator;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator;
import com.opensymphony.xwork2.validator.annotations.Validations;
import com.systop.cms.utils.PageUtil;
import com.systop.common.modules.area.service.AreaManager;
import com.systop.common.modules.dept.model.Dept;
import com.systop.common.modules.dept.webapp.DeptAction;
import com.systop.common.modules.security.user.UserConstants;
import com.systop.common.modules.security.user.UserUtil;
import com.systop.common.modules.security.user.model.User;
import com.systop.common.modules.security.user.service.UserManager;
import com.systop.core.Constants;
import com.systop.core.dao.support.Page;
import com.systop.core.util.RequestUtil;
import com.systop.core.webapp.struts2.action.ExtJsCrudAction;
import com.systop.core.webapp.upload.UpLoadUtil;

/**
 * <code>User</code>对象的struts2 action。
 * 
 * @author Sam Lee
 */
@SuppressWarnings({ "serial", "unchecked", "rawtypes" })
@Controller
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class UserAction extends ExtJsCrudAction<User, UserManager> {

	/** 对应页面查询条件 */
	private String queryUsername;

	/** 对应页面查询条件:部门名称 */
	private String deptId;

	/** 查询起始时间 */
	private Date beginDate;

	/** 查询结束时间 */
	private Date endDate;

	/** 修改密码的时候对应输入的旧密码 */
	private String oldPassword;

	/** 标识是否是用户自行修改个人信息，如果为<code>null</code>则表示 由管理员修改。否则，表示由用户自己修改 */
	private String selfEdit;

	/** 当前登录用户 */
	private User user;

	/**
	 * 检测用户返回的结果
	 */
	private Map<String, String> checkResult;

	/**
	 * 保存用户树形列表
	 */
	private List<Map> userTree;
	/**
	 * 上级部门ID，用于列出树形列表
	 */
	private Integer parentDeptId;

	/**
	 * 角色名称，用于员工选择器
	 */
	private String roleName;

	/**
	 * 注册用户登陆名,用于ajax验证.userName:loginId
	 */
	private String userName;

	/**
	 * 注册用户ID,用于ajax验证 userId:主键
	 */
	private String userId;

	/**
	 * 注册用户email,用于ajax验证
	 */
	private String emailStr;
	
	/**
	 * 查看代理商[客户的归属类型]:[个人、全部]
	 */
	private String showAgentType;
	
	private String showAgentTypeSelf = "self";

	/** 异步修改密码返回消息 */
	private String msg;

	@Autowired
	private DeptAction deptAction;

	/** 部门管理 @Autowired */
	// private DeptManager deptManager;

	/**  登陆用户信息管理  @Autowired*/
	// private LoginUserService loginUserService;
	
	/**
	 * 对应上传图片的原始文件名，新文件名在getModel().getPhoto()
	 */
	private File userPhoto;

	/**
	 * 对应上传图片的原始文件名，新文件名在getModel().getPhoto()
	 */
	private String userPhotoFileName;
	
	@Autowired
	private AreaManager areaManager;

	/**
	 * 为默认的index.do查询数据，用户类型都为员工,即<code>UserConstants.USER_TYPE_STAFF:1</code>
	 */
	@Override
	protected Page pageQuery() {
		DetachedCriteria criteria = setupDetachedCriteria();
		criteria.add(Restrictions.eq("type", UserConstants.USER_TYPE_STAFF));
		Page page = new Page(Page.start(getPageNo(), getPageSize()), getPageSize());
		return getManager().pageQuery(page, criteria);
	}

	/**
	 * @return DetachedCriteria 查询条件
	 */
	private DetachedCriteria setupDetachedCriteria() {
		DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
		Example example = Example.create(getModel()).ignoreCase().setPropertySelector(
				//选择不为null的属性作为查询条件
				new PropertySelector() {
					public boolean include(Object propertyValue,
							String propertyName, Type type) {
						return propertyValue != null
								&& StringUtils.isNotBlank(propertyValue
										.toString());
					}
				}).enableLike(MatchMode.ANYWHERE);
		criteria.add(example);
		Order order = Order.desc("status");
		criteria.addOrder(order);
		logger.info(criteria.toString());
		return setupSort(criteria);
	}
	
	/**
	 * 查询分销商和终端用户，即用户类型为<code>2,3</code>
	 * @return
	 */
	public String agentsIndex(){
		User u = UserUtil.getPrincipal(getRequest());
		Assert.notNull(u, "用户未登录");
		DetachedCriteria  criteria = setupDetachedCriteria();
		//查查用户类别为分销商和终端客户的User
		criteria.add(Restrictions.in("type", new String[]{UserConstants.USER_TYPE_AGENTS, UserConstants.USER_TYPE_CUSTOMERS}));
		if (StringUtils.isBlank(showAgentType) || showAgentTypeSelf.equals(showAgentType)){
			criteria.add(Restrictions.eq("manager.id", u.getId()));
		}else{
			
		}
		//String myarecode = "130000,140000";
		criteria.add(Restrictions.like("areaCode", "13%"));
		criteria.add(Restrictions.like("areaCode", "14%"));
		
		Page page = PageUtil.getPage(getPageNo(), getPageSize());
		page = getManager().pageQuery(page, criteria);
		restorePageData(page);
		return "agents";
	}
	
	/**
	 * 查询终端用户customer[3]
	 * @return
	 */
	public String customerIndex(){
		User manager = UserUtil.getPrincipal(getRequest());
		Assert.notNull(manager, "当前登录用户为空");
		DetachedCriteria  criteria = setupDetachedCriteria();
		criteria.add(Restrictions.eq("type", UserConstants.USER_TYPE_CUSTOMERS));
		//查询自己管理的终端客户
		criteria.add(Restrictions.eq("manager.id", manager.getId()));
		Page page = PageUtil.getPage(getPageNo(), getPageSize());
		page = getManager().pageQuery(page, criteria);
		restorePageData(page);
		return "customerIndex";
	}
	
	/**
	 * 编辑个人信息
	 * 暂时用的是edit.do 回头调整
	 * @return
	 */
	public String selfEdit(){
		selfEdit = Constants.CHAR_TRUE;
		return INPUT;
	}

	@Validations(requiredStrings = {
			@RequiredStringValidator(fieldName = "model.loginId", message = "登录名是必须的."),
			@RequiredStringValidator(fieldName = "model.password", message = "密码是必须的."),
			@RequiredStringValidator(fieldName = "model.confirmPwd", message = "请两次输入密码.") }, stringLengthFields = { @StringLengthFieldValidator(fieldName = "password", maxLength = "32", message = "密码应少于32字符", trim = true) }, emails = { @EmailValidator(fieldName = "model.email", message = "请输入正确的e-Mail.") }, expressions = { @ExpressionValidator(message = "两次输入的密码必须相同.", expression = "model.password==model.confirmPwd") })
	@Override
	public String save() {
		Assert.notNull(getModel());
		if (getModel().getId() == null) {
			getModel().setStatus(UserConstants.USER_STATUS_USABLE);
		}
		//部门设置的问题容易出现异常，所以这么操作，清晰一些
		String deptId = getRequest().getParameter("deptId");
		if (StringUtils.isNotBlank(deptId)){
			Dept dept = getManager().getDao().get(Dept.class, Integer.valueOf(deptId));
			getModel().setDept(dept);
		}
		
		if (userPhoto != null) {
			long fileSize = userPhoto.length()/1024;
			if (fileSize > 100){
				this.addActionError("上传文件过大[" + fileSize + "KB]，应小于100KB");
				return INPUT;
			}
			String photoPath = UpLoadUtil.doUpload(userPhoto, userPhotoFileName,
					UserConstants.USER_PHOTO_PATH, getServletContext(), true);
			getModel().setPhoto(photoPath);
		}
		String areaCode = getAreaCode();
		if (areaCode != null){
			getModel().setAreaCode(areaCode);
			getModel().setAreaName(areaManager.getAllAreaName(areaCode));
		}
		if (!UserConstants.USER_TYPE_STAFF.equals(getModel().getType())){//非员工保存设置Manager
			User manager = UserUtil.getPrincipal(getRequest());
			getModel().setManager(manager);
		}
		
		super.save();
		if (isSelfEdit()) {
			logger.debug("用户自己修改个人信息.");
			addActionMessage("用户信息已经成功修改。");
			return INPUT;
		} 
		
		if (UserConstants.USER_TYPE_STAFF.equals(getModel().getType())){
			return SUCCESS;
		} else if(UserConstants.USER_TYPE_AGENTS.equals(getModel().getType())) {
			return "agentsSuccess";
		}else{
			return "customerSuccess";
		}
	}
	
	private String getAreaCode(){
		String areaCode = null;
		String province = getRequest().getParameter("province");
		String city = getRequest().getParameter("city");
		String county = getRequest().getParameter("county");
		if (StringUtils.isNotBlank(province)){
			areaCode = province;
		} 
		if (city != null && ! "0".equals(city)){
			areaCode = city;
		}
		
		if (county != null && ! "0".equals(county)){
			areaCode = county;
		}
		return areaCode;
	}
	
	public String deleteUserPhoto(){
		
		if (getModel().getId() != null){
			User u = getManager().get(getModel().getId());
			if (u == null){
				return "delphoto";
			}
			if (StringUtils.isNotBlank(u.getPhoto())){
				File photo = new File(getServletContext().getRealPath(u.getPhoto()));
				if (photo.exists()){
					photo.delete();
				}
				u.setPhoto(null);
				getManager().save(u);
				msg = "{success:true}";
			}
		}
		return "delphoto";
	}

	/**
	 * 编辑用户
	 */
	@SkipValidation
	@Override
	public String editNew() {
		getModel().setSex(UserConstants.GENT);
		return INPUT;
	}

	/**
	 * 修改密码
	 */
	public String changePassword() {
		if (StringUtils.isBlank(oldPassword) || getModel() == null
				|| getModel().getId() == null) {
			return "changePassword";
		}
		String pwdToShow = getModel().getPassword();
		try {
			getManager().changePassword(getModel(), oldPassword);
			addActionMessage("修改密码成功，新密码是：" + pwdToShow);
		} catch (Exception e) {
			addActionError(e.getMessage());
		}
		return "changePassword";
	}

	/**
	 * 为异步请求修改密码
	 * 
	 * @return
	 */
	public String changePassAjax() {
		String username = getRequest().getParameter("username");
		String newpass = getRequest().getParameter("newpass");
		try {
			getManager().changePassword(username, newpass);
			msg = "{success:true}";
		} catch (Exception e) {
			msg = "{failure:true}";
			e.printStackTrace();
		}
		return JSON;
	}

	/**
	 * 启用用户
	 * 
	 * @return
	 */
	public String unsealUser() {
		if (ArrayUtils.isEmpty(selectedItems)) {
			if (getModel() != null) {
				Serializable id = extractId(getModel());
				if (id != null) {
					selectedItems = new Serializable[] { id };
				}
			}
		}
		if (selectedItems != null) {
			for (Serializable id : selectedItems) {
				if (id != null) {
					User user = getManager().get(convertId(id));
					if (user != null) {
						getManager().unsealUser(user);
					} else {
						logger.debug("用户信息不存在.");
					}
				}
			}
			logger.debug("{} items usable user.", selectedItems.length);
		}
		return SUCCESS;
	}

	public String showSelf() {
		if (getModel().getId() != null) {
			setModel(getManager().get(getModel().getId()));
		}
		return "bingo";
	}

	/**
	 * 前台注册用户修改个人信息
	 * 
	 * @return
	 */
	public String editInfo() {
		user = UserUtil.getPrincipal(getRequest());
		getModel().setLoginId(user.getLoginId());
		getModel().setPassword(user.getPassword());
		if (isSelfEdit()) {
			getManager().update(getModel());
			addActionMessage("个人信息修改成功!");
		}
		return "bingo";
	}

	/**
	 * Build a tree as json format.
	 */
	@SkipValidation
	public String userTree() {
		if (RequestUtil.isJsonRequest(getRequest())) {
			Dept parent = null;
			if (parentDeptId != null) {
				parent = getManager().getDao().get(Dept.class, parentDeptId);
			} else {
				parent = (Dept) getManager().getDao().findObject(
						"from Dept d where d.parentDept is null");
			}
			Map<String, Object> parentMap = null;
			if (parent != null) {
				parentMap = new HashMap<String, Object>();
				parentMap.put("id", parent.getId());
				parentMap.put("text", parent.getName());
				parentMap.put("type", parent.getType());
			}
			Map deptTree = deptAction.getDeptTree(parentMap, true);
			Map tree = getManager().getUserTree(deptTree, roleName);
			if (!tree.isEmpty()) {
				userTree = new ArrayList<Map>();
				userTree.add(tree);
			}
			return "tree";
		}
		return INDEX;
	}

	/**
	 * 2010-1-13 yj 用户登录记录查询
	 */
	public String userHistoryList() {

		// Dept county = loginUserService.getLoginUserCounty(getRequest());
		Page page = PageUtil.getPage(getPageNo(), getPageSize());
		StringBuffer hql = new StringBuffer(
				"from UserLoginHistory  ulh  where 1=1 ");
		List args = new ArrayList();
		if (StringUtils.isNotBlank(queryUsername)) {
			hql.append(" and ulh.user.name like ? ");
			args.add("%" + queryUsername + "%");
		}
		/*
		 * 关于部门查询取消 if (deptId == null || deptId.equals("")) { if
		 * (county.getParentDept() != null) {// 区县
		 * hql.append(" and ulh.dept.id =? "); args.add(county.getId()); } }
		 * else { Dept dt = deptManager.findObject("from Dept d where d.id =?",
		 * Integer.valueOf(deptId)); if (dt.getParentDept() != null) {// 区县
		 * hql.append(" and ulh.dept.id =? ");
		 * args.add(Integer.valueOf(deptId)); } }
		 */
		if (beginDate != null && endDate != null) {
			hql.append("and ulh.loginTime >= ? and ulh.loginTime <= ? ");
			args.add(beginDate);
			args.add(endDate);
		}
		hql.append(" order by ulh.loginTime desc ");
		page = getManager().pageQuery(page, hql.toString(), args.toArray());
		restorePageData(page);

		/*
		 * 取消与部门相关 if (StringUtils.isNotBlank(deptId)) { Dept dp =
		 * deptManager.findObject("from Dept d where d.id=?",
		 * Integer.valueOf(deptId)); getRequest().setAttribute("deptName",
		 * dp.getName()); } else { getRequest().setAttribute("deptName",
		 * county.getName()); }
		 */
		return "userHistoryList";
	}

	/**
	 * ajax请求，检测登录名是否已存在
	 */
	public String checkName() {
		List<User> list = getManager()
				.getUserByName(getUserId(), getUserName());
		checkResult = Collections
				.synchronizedMap(new HashMap<String, String>());
		if (list != null && list.size() > 0) {
			checkResult.put("result", "exist");
		} else {
			checkResult.put("result", "notExist");
		}
		return "jsonRst";
	}

	/**
	 * ajax请求，检测用户邮箱是否已存在
	 */
	public String checkEmail() {
		List<User> list = getManager().getUserByEmail(getUserId(),
				getEmailStr());
		checkResult = Collections
				.synchronizedMap(new HashMap<String, String>());
		if (list != null && list.size() > 0) {
			checkResult.put("result", "exist");
		} else {
			checkResult.put("result", "notExist");
		}
		return "jsonRst";
	}

	/**
	 * 取得用户登陆后的信息
	 */
	public String userInfo() {
		user = UserUtil.getPrincipal(getRequest());
		return "userInfo";
	}

	/**
	 * 返回性别Map
	 */
	public Map<String, String> getSexMap() {
		return UserConstants.SEX_MAP;
	}

	/**
	 * 是否用户自己修改信息
	 */
	private boolean isSelfEdit() {
		return StringUtils.isNotBlank(selfEdit);
	}

	/**
	 * @return the queryUsername
	 */
	public String getQueryUsername() {
		return queryUsername;
	}

	/**
	 * @param queryUsername
	 *            the queryUsername to set
	 */
	public void setQueryUsername(String queryUsername) {
		this.queryUsername = queryUsername;
	}

	/**
	 * @return the oldPassword
	 */
	public String getOldPassword() {
		return oldPassword;
	}

	/**
	 * @param oldPassword
	 *            the oldPassword to set
	 */
	public void setOldPassword(String oldPassword) {
		this.oldPassword = oldPassword;
	}

	/**
	 * @return the selfEdit
	 */
	public String getSelfEdit() {
		return selfEdit;
	}

	/**
	 * @param selfEdit
	 *            the selfEdit to set
	 */
	public void setSelfEdit(String selfEdit) {
		this.selfEdit = selfEdit;
	}

	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	/**
	 * @param user
	 *            the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}

	public List<Map> getUserTree() {
		return userTree;
	}

	public void setUserTree(List<Map> userTree) {
		this.userTree = userTree;
	}

	public Integer getParentDeptId() {
		return parentDeptId;
	}

	public void setParentDeptId(Integer parentDeptId) {
		this.parentDeptId = parentDeptId;
	}

	public String getRoleName() {
		return roleName;
	}

	public void setRoleName(String roleName) {
		this.roleName = roleName;
	}

	public Date getBeginDate() {
		return beginDate;
	}

	public void setBeginDate(Date beginDate) {
		this.beginDate = beginDate;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

	public String getDeptId() {
		return deptId;
	}

	public void setDeptId(String deptId) {
		this.deptId = deptId;
	}

	public Map<String, String> getCheckResult() {
		return checkResult;
	}

	public void setCheckResult(Map<String, String> checkResult) {
		this.checkResult = checkResult;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getEmailStr() {
		return emailStr;
	}

	public void setEmailStr(String emailStr) {
		this.emailStr = emailStr;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public File getUserPhoto() {
		return userPhoto;
	}

	public void setUserPhoto(File userPhoto) {
		this.userPhoto = userPhoto;
	}

	public String getUserPhotoFileName() {
		return userPhotoFileName;
	}

	public void setUserPhotoFileName(String userPhotoFileName) {
		this.userPhotoFileName = userPhotoFileName;
	}

	public AreaManager getAreaManager() {
		return areaManager;
	}

	public void setAreaManager(AreaManager areaManager) {
		this.areaManager = areaManager;
	}

	public String getShowAgentType() {
		return showAgentType;
	}

	public void setShowAgentType(String showAgentType) {
		this.showAgentType = showAgentType;
	}
	
}
